package com.ruoyi.factory.manpower.utils;

import cn.hutool.crypto.SecureUtil;
import org.springframework.util.StringUtils;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

/**
 * 签名工具类
 *
 * @author WEIXING
 * @date 2020/11/25 18:49
 */
public class OpenSignUtil {

    //region SHA256签名和验签

    /**
     * 对参数进行SHA256签名
     *
     * @param dataMap 要签名的参数
     * @param signKey    签名密钥
     * @return
     * @throws Exception
     */
    public static String sha256Sign(Map<String, String> dataMap, String signKey) throws Exception {
        //待签名数据
        String content = signContent(dataMap, UrlType.DECODE, signKey);
        //进行签名
        String sign = SecureUtil.sha256(content);
        if (sign != null) {
            sign = sign.toUpperCase();
        }
        return sign;
    }

    /**
     * 对参数进行SHA256验签
     *
     * @param dataMap 要验签的参数
     * @param sign       签名值
     * @param signKey    签名密钥
     * @return
     * @throws Exception
     */
    public static boolean sha256CheckSign(Map<String, String> dataMap, String sign, String signKey) throws Exception {
        //待验签数据
        String content = signContent(dataMap, UrlType.DECODE, signKey);
        //进行签名
        String signNew = SecureUtil.sha256(content);
        if (signNew != null) {
            signNew = signNew.toUpperCase();
        }
        //验证签名是否一致
        return Objects.equals(sign, signNew);
    }

    //endregion

    //region 参数转待签名数据

    /**
     * 获得待签名/验签的数据
     *
     * @param dataMap 参数数据
     * @param urlType url编解码类型
     * @return
     * @throws Exception
     */
    private static String signContent(Map<String, String> dataMap, UrlType urlType) throws Exception {
        return signContent(dataMap, urlType, null);
    }

    /**
     * 获得待签名/验签的数据
     *
     * @param dataMap 参数数据
     * @param urlType url编解码类型
     * @param signKey 签名的密钥
     * @return
     * @throws Exception
     */
    private static String signContent(Map<String, String> dataMap, UrlType urlType, String signKey) throws Exception {
        StringBuilder sb = new StringBuilder();
        Set<String> keys = dataMap.keySet();
        List<String> keyList = new ArrayList<String>();
        for (String key : keys) {
            keyList.add(key);
        }
        //排序
        Collections.sort(keyList);
        for (String key : keyList) {
            if (!StringUtils.hasText(key)) {
                continue;
            }
            if (OpenConstant.SIGN.equals(key.toLowerCase())) {
                continue;
            }
            String val = dataMap.get(key);
            if (!StringUtils.hasText(val)) {
                continue;
            }
            if (urlType == UrlType.ENCODE) {
                //对数据进行URL编码
                val = URLEncoder.encode(val, OpenConstant.CHARSET);
            } else if (urlType == UrlType.DECODE) {
                //对数据进行URL解码
                val = URLDecoder.decode(val, OpenConstant.CHARSET);
            }
            sb.append(key).append("=").append(val).append("&");
        }
        String signContent;
        if (StringUtils.hasText(signKey)) {
            signContent = sb.append("key=" + signKey).toString();
        } else {
            if (sb.length() > 1) {
                signContent = sb.substring(0, sb.length() - 1);
            } else {
                signContent = sb.toString();
            }
        }
        return signContent;
    }

    //endregion

}

